/**
 * @Company：泰康人寿保险股份有限公司 Copyright Taikanglife.All Rights Reserved 2014
 */
package com.snow.springboot.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Package: com.taikanglife.bms.util
 * @ClassName: DateUtil
 * @Description: 公共工具类
 * @Author lurui04
 * @Date: 2017/6/8 13:16
 */
public class DateUtil {

    private static Logger logger = LoggerFactory.getLogger(DateUtil.class);

    /**
     * @return String "2012-03-08 01:11:23"
     * @Title: getCurrentTimeBySecond
     * @Description: 获取年月日时分秒
     */
    public static String getCurrentTimeBySecond() {
        Date date = new Date();
        SimpleDateFormat dateFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        return dateFormate.format(date);
    }

    /**
     * @return String 2012-05-09
     * @Title: getCurrentTimeByDay
     * @Description: 返回当前日期
     */
    public static String getCurrentTimeByDay() {
        Date date = new Date();
        SimpleDateFormat dateFormate = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
        return dateFormate.format(date);
    }

    /**
     * 计算指定时间的天数之前的时间（年月日时分秒）
     *
     * @param dateStr   指定时间
     *                  <br><i>正：向后；负：向前</i></br>
     * @param yearNum   年数
     * @param monthNum  月数
     * @param dayNum    天数
     * @param hourNum   时数
     * @param minuteNum 分数
     * @param secondNum 秒数
     * @return String "2012-03-08 01:11:23"
     * @throws ParseException
     */
    public static String getDateAlter(String dateStr, int yearNum,
                                      int monthNum, int dayNum, int hourNum, int minuteNum, int secondNum)
        throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        Date date = sdf.parse(dateStr);
        Date dateAlter = getDateAlter(date, yearNum, monthNum, dayNum, hourNum, minuteNum, secondNum);
        return sdf.format(dateAlter);
    }

    /**
     * @param millis 指定毫秒值
     * @return String "2012-03-08 01:11:23"
     * @Title: getDateBySpecifyMillis
     * @Description: 根据指定毫秒值格式化日期（年月日时分秒）
     */
    public static String getDateBySpecifyMillis(long millis) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        return sdf.format(new Date(millis));
    }


    /**
     * @Title: difHoursByMillisecond
     * @Description: 比较两个时间相差的天数
     * @Param: [dateStart, dateEnd]
     * @Return: int
     * @Date: 2017/6/15 10:39
     * @Author: lurui04
     */
    public static int difDaysByMillisecond(Date dateStart, Date dateEnd) throws Exception {
        int days = (int) ((dateEnd.getTime() - dateStart.getTime()) / (1000 * 3600 * 24));
        return days;
    }


    /**
     * @Title: getDateByString
     * @Description:将String类型的时间（yyyy-MM-dd HH:mm:ss）转换成date
     * @Param: [strTime]
     * @Return: java.util.Date
     * @Date: 2017/6/15 10:41
     * @Author: lurui04
     */
    public static Date getDateByString(String strTime) {
        return getDateFromString(strTime,"yyyy-MM-dd HH:mm:ss");
    }

    public static Date getDateFromString(String dateStr, String format){
        SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.CHINA);
        Date date = null;
        try {
            date = formatter.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
            logger.error("strTime#{}类型转换失败。", dateStr);
        }
        return date;
    }

    /**
     * @Title: getLongByString
     * @Description: 将String类型的时间（yyyy-MM-dd HH:mm:ss）转换成long
     * @Param: [strTime]
     * @Return: long
     * @Date: 2017/6/15 14:09
     * @Author: lurui04
     */
    public static long getLongByString(String strTime) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(strTime);
        return date.getTime() / 1000;
    }



    /**
     * @Title: getStringByDate
     * @Description: 根据日期获取格式化后的时间
     * @Param: [date, format]
     * @Return: java.lang.String
     * @author: liucx47
     * @Date: 2018/3/5 13:48
     **/
    public static String getStringByDate(Date date, String format) {
        SimpleDateFormat dateFormate = new SimpleDateFormat(format, Locale.CHINA);

        return dateFormate.format(date);
    }

    /**
     * @Title: getStartOfDay
     * @Description: 获取日期的0点0分0秒
     * @Param: [date]
     * @Return: java.util.Date
     * @author: liucx47
     * @Date: 2018/3/5 13:55
     **/
    public static Date getStartOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zero = calendar.getTime();

        return zero;
    }

    /**
     * 获取指定日期间隔中的所有日期,输出为字符串的list集合
     */
    public static List<String> getFullDate(Date startDate, Date endDate) throws Exception {
        if(startDate.getTime() > endDate.getTime()){
            return null;
        }
        int interval = difDaysByMillisecond(startDate, endDate) + 1;
        List<String> dateList = new ArrayList<>(interval);
        Date temp = startDate;
        for (int i = 0; i < interval; i++) {
            dateList.add(getStringByDate(temp));
            temp = new Date(temp.getTime() + 24*3600*1000);
        }
        return dateList;
    }

    /**
     * 将时间对象Date转换为 yyyy-MM-dd格式的字符串
     */
    public static String getStringByDate(Date date){
        return getStringByDate(date,"yyyy-MM-dd");
    }

    /**
     * @Description 获取传入的两个时间区间的交集
     * @author zhiwei
     * @param timeSectionFirst 第一个时间区间,字符串的数组,元素个数为2,每个元素的格式为yyyy-MM-dd HH:mm:ss
     * @param timeSectionSecond 第二个时间区间,字符串的数组,元素个数为2,每个元素的格式为yyyy-MM-dd HH:mm:ss
     * @return 如果有交集则返回交集的数组,共两个元素,每个元素都是格式为yyyy-MM-dd HH:mm:ss的时间字符串    如果没有交集或者传入的时间区间格式异常则返回null
     * @Date: 2018/5/16 13:55
     */
    public static String[] getIntersection(String[] timeSectionFirst,String[] timeSectionSecond){
        //转换参数格式
        Date firstBeginDate = getDateByString(timeSectionFirst[0]);
        Date firstEndDate = getDateByString(timeSectionFirst[1]);
        Date secondBeginDate = getDateByString(timeSectionSecond[0]);
        Date secondEndDate = getDateByString(timeSectionSecond[1]);
        //校验参数
        if(null == firstBeginDate || null == firstEndDate || null == secondBeginDate || null == secondEndDate){
            return null;
        }
        //生成结果容器,存放交集起止时间的数组
        String[] result = new String[2];
        //有交集 且 firstBeginDate >= secondBeginDate
        if(firstBeginDate.getTime() >= secondBeginDate.getTime() && firstBeginDate.getTime() <= secondEndDate.getTime()){
            result[0] = timeSectionFirst[0];
            result[1] = firstEndDate.getTime() <= secondEndDate.getTime() ? timeSectionFirst[1] : timeSectionSecond[1];
            return result;
        }
        //有交集 且 firstBeginDate < secondBeginDate
        if(secondBeginDate.getTime() > firstBeginDate.getTime() && secondBeginDate.getTime() <= firstEndDate.getTime()){
            result[0] = timeSectionSecond[0];
            result[1] = firstEndDate.getTime() <= secondEndDate.getTime() ? timeSectionFirst[1] : timeSectionSecond[1];
            return result;
        }
        //没有交集
        return null;
    }

    /**
     * @Title: getStartOfDay
     * @Description: 获取开始时间和结束时间跨度内,为开始时间为起始时间,每间隔一个月的时间字符串
     * @Param: [start, end, dateFormat] 开始时间,结束时间,返回时间字符串的格式
     * @Return: java.lang.String[]
     * @author: Zhi.wei
     * @Date: 9:52 2018/6/21
     **/
    /*public static String[] getTimestamp(Date start, Date end,String dateFormat) throws EndTimeBeforeStartTimeException {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat, Locale.CHINA);
        int count = difMonthsByTimestamp(start, end) + 1;
        String[] dates = new String[count];
        dates[0]=sdf.format(start);
        if(count > 1) {
            for (int i = 1; i < count; i++) {
                dates[i] = sdf.format(getDateAlter(start, 0, i, 0, 0, 0, 0));
            }
        }
        return dates;
    }*/

    /**
     * 计算指定时间的天数之前(后)的时间（年月日时分秒）
     * @param dateStr   指定时间
     *                  <br><i>正：向后；负：向前</i></br>
     * @param yearNum   年数
     * @param monthNum  月数
     * @param dayNum    天数
     * @param hourNum   时数
     * @param minuteNum 分数
     * @param secondNum 秒数
     * @return Date
     * @author: Zhi.wei
     * @Date: 14:34 2018/6/13
     **/
    private static Date getDateAlter(Date dateStr, int yearNum, int monthNum, int dayNum, int hourNum, int minuteNum, int secondNum) {
        Calendar cal = Calendar.getInstance(Locale.CHINA);
        cal.setTime(dateStr);
        cal.add(Calendar.YEAR, yearNum);
        cal.add(Calendar.MONTH, monthNum);
        cal.add(Calendar.DATE, dayNum);
        cal.add(Calendar.HOUR_OF_DAY, hourNum);
        cal.add(Calendar.MINUTE, minuteNum);
        cal.add(Calendar.SECOND, secondNum);
        return cal.getTime();
    }

    /**
     * 设置指定的时间（年月日时分秒）
     * @param dateStr   指定初始时间
     * @param yearNum   年数
     * @param monthNum  月数
     * @param dayNum    天数
     * @param hourNum   时数
     * @param minuteNum 分数
     * @param secondNum 秒数
     * @return Date
     * @author: Zhi.wei
     * @Date: 14:34 2018/6/14
     **/
    private static Date getAssignDate(Date dateStr, Integer yearNum, Integer monthNum, Integer dayNum, Integer hourNum, Integer minuteNum, Integer secondNum) {
        Calendar cal = Calendar.getInstance(Locale.CHINA);
        cal.setTime(dateStr);
        if(null != yearNum){
            cal.set(Calendar.YEAR,yearNum);
        }
        if(null != monthNum){
            cal.set(Calendar.MONDAY,monthNum-1);
        }
        if(null != dayNum){
            cal.set(Calendar.DAY_OF_MONTH,dayNum);
        }
        if(null != hourNum){
            cal.set(Calendar.HOUR,hourNum);
        }
        if(null != minuteNum){
            cal.set(Calendar.MINUTE,minuteNum);
        }
        if(null != secondNum){
            cal.set(Calendar.SECOND,secondNum);
        }
        return cal.getTime();
    }

    /**
     * @Title: getStartOfDay
     * @Description: 传入指定格式的日期字符串,返回日期所在月份的时间跨度,精确到秒
     * @Param: [month] 日期字符串
     * @Param: [format] 指定参数格式
     * @Param: [format] 指定返回值格式
     * @Return: java.lang.String[] 返回两个元素的数字,第一个为所在月的第一秒,第二个为所在月份的最后一秒
     * @author: Zhi.wei
     * @Date: 10:15 2018/6/15
     **/
    public static String[] getFirstTimeAndLastTimeOfmonth(String month, String paramFormat, String returnFormat){
        Date dateFromString = getDateFromString(month, paramFormat);
        Date firstSecond = getAssignDate(dateFromString, null, null, 1, 0, 0, 0);
        Date lastSecond = getDateAlter(firstSecond,0,1,0,0,0,-1);
        return new String[]{getStringByDate(firstSecond,returnFormat),getStringByDate(lastSecond,returnFormat)};
    }

    /**
     * @Description: 比较两个时间相差的月数,要求结束时间必须大于等于开始时间,否则抛异常
     * @Param: [dateStart, dateEnd]
     * @Return: Integer
     * @Date: 2018/6/13 10:39
     * @Author: zhiwei
     */
    /*private static int difMonthsByTimestamp(Date dateStart, Date dateEnd) throws EndTimeBeforeStartTimeException {
        if (dateStart.after(dateEnd)){
            throw new EndTimeBeforeStartTimeException(dateEnd + "早于" + dateStart);
        }
        Calendar start = Calendar.getInstance();
        start.setTime(dateStart);
        Calendar end = Calendar.getInstance();
        end.setTime(dateEnd);

        int subMonthCount;
        if(end.get(Calendar.YEAR) - start.get(Calendar.YEAR) == 0){
            //同一年
            subMonthCount = end.get(Calendar.MONTH) - start.get(Calendar.MONTH);
        }else{
            //不是同一年
            subMonthCount = (end.get(Calendar.YEAR) - start.get(Calendar.YEAR) - 1) * 12
                    + start.getActualMaximum(Calendar.MONTH) - start.get(Calendar.MONTH)  + end.get(Calendar.MONTH) + 1;
        }
        return subMonthCount;
    }*/
}
